<template>
  <el-card>
    <span slot="header"> 节点缓存配置 </span>
    <el-form ref="form" :model="formData" label-width="150px">
      <el-form-item label="默认缓存方式" prop="CacheType">
        <el-select v-model="formData.CacheType" placeholder="缓存类型" @change="chioseCacheType">
          <el-option label="Memcached" :value="0" />
          <el-option label="Redis" :value="1" />
          <el-option label="Local" :value="2" />
        </el-select>
      </el-form-item>
    </el-form>
    <el-tabs v-model="activeName" type="border-card" style="width: 100%;">
      <el-tab-pane label="Memcached" name="memcached">
        <el-form ref="memcached" :rules="memcachedRules" :model="memcached" label-position="top">
          <el-form-item
            label="服务IP"
            prop="ServerIp"
          >
            <el-row v-for="(item, index) in memcached.ServerIp" :key="index" style="width: 400px;margin-bottom:10px;">
              <el-input
                v-model="item.value"
                placeholder="服务IP"
                style="width: 380px"
                @blur="()=>checkIp(item)"
              >
                <el-button slot="append" @click="removeIp(index)">删除</el-button>
              </el-input>
              <p v-if="item.isError" style="color: red;">{{ item.error }}</p>
            </el-row>
            <el-button @click="addIp">新增IP</el-button>
          </el-form-item>
          <el-form-item label="最小链接数" prop="MinPoolSize">
            <el-input-number v-model="memcached.MinPoolSize" :min="1" />
          </el-form-item>
          <el-form-item label="最大链接数" prop="MaxPoolSize">
            <el-input-number v-model="memcached.MaxPoolSize" :min="1" />
          </el-form-item>
          <el-form-item label="链接超时时间(秒)" prop="ConnectionTimeout">
            <el-input-number v-model="memcached.ConnectionTimeout" :min="1" />
          </el-form-item>
          <el-form-item label="用户名" prop="UserName">
            <el-input v-model="memcached.UserName" placeholder="用户名" maxlength="50" />
          </el-form-item>
          <el-form-item label="密码" prop="Pwd">
            <el-input v-model="memcached.Pwd" placeholder="密码" maxlength="50" />
          </el-form-item>
        </el-form>
      </el-tab-pane>
      <el-tab-pane label="Redis" name="redis">
        <el-form ref="redis" :model="redis" :rules="redisRules" label-position="top">
          <el-form-item
            label="服务IP"
            prop="ServerIp"
          >
            <el-row v-for="(item, index) in redis.ServerIp" :key="index" style="width: 400px;margin-bottom:10px;">
              <el-input
                v-model="item.value"
                placeholder="服务IP"
                style="width: 380px"
                @blur="()=>checkIp(item)"
              >
                <el-button slot="append" @click="removeRedisIp(index)">删除</el-button>
              </el-input>
              <p v-if="item.isError" style="color: red;">{{ item.error }}</p>
            </el-row>
            <el-button @click="addRedisIp">新增IP</el-button>
          </el-form-item>
          <el-form-item label="模式" prop="CommandMap">
            <el-select v-model="redis.CommandMap" placeholder="模式">
              <el-option label="Default" :value="0" />
              <el-option label="Twemproxy" :value="1" />
              <el-option label="Envoyproxy" :value="2" />
              <el-option label="SSDB" :value="3" />
              <el-option label="Sentinel" :value="4" />
            </el-select>
          </el-form-item>
          <el-form-item label="链接字符串" prop="ConString">
            <el-input v-model="redis.ConString" />
          </el-form-item>
          <el-form-item label="默认DB" prop="DefaultDatabase">
            <el-input-number v-model="redis.DefaultDatabase" :min="0" :max="15" />
          </el-form-item>
          <el-form-item label="允许管理操作" prop="AllowAdmin">
            <el-switch v-model="redis.AllowAdmin" />
          </el-form-item>
          <el-form-item label="Ping间隔(秒)" prop="KeepAlive">
            <el-input-number v-model="redis.KeepAlive" :min="1" />
          </el-form-item>
          <el-form-item label="链接重试次数" prop="ConnectRetry">
            <el-input-number v-model="redis.ConnectRetry" :min="1" />
          </el-form-item>
          <el-form-item label="同步超时" prop="SyncTimeout">
            <el-input-number v-model="redis.SyncTimeout" :min="1" />
          </el-form-item>
          <el-form-item label="异步超时" prop="AsyncTimeout">
            <el-input-number v-model="redis.AsyncTimeout" :min="1" />
          </el-form-item>
          <el-form-item label="链接超时" prop="ConnectTimeout">
            <el-input-number v-model="redis.ConnectTimeout" :min="1" />
          </el-form-item>
          <el-form-item label="检查证书吊销列表" prop="CheckCertificateRevocation">
            <el-switch v-model="redis.CheckCertificateRevocation" />
          </el-form-item>
          <el-form-item label="通过sentinel解析服务的服务名称" prop="ServiceName">
            <el-input v-model="redis.ServiceName" placeholder="服务名称" />
          </el-form-item>
          <el-form-item label="库是否应通过库名称/版本标识自身" prop="SetClientLibrary">
            <el-switch v-model="redis.SetClientLibrary" />
          </el-form-item>
          <el-form-item label="每隔n秒（默认情况下每分钟）检查一次配置" prop="ConfigCheckSeconds">
            <el-input-number v-model="redis.ConfigCheckSeconds" :min="1" />
          </el-form-item>
          <el-form-item label="用于广播和收听配置更改通知的频道" prop="ConfigurationChannel">
            <el-input v-model="redis.ConfigurationChannel" />
          </el-form-item>
          <el-form-item label="连接不正常时用于命令的囤积策略" prop="BacklogPolicy">
            <el-select v-model="redis.BacklogPolicy" placeholder="连接不正常时用于命令的囤积策略">
              <el-option label="FailFast" :value="0" />
              <el-option label="Default" :value="1" />
            </el-select>
          </el-form-item>
          <el-form-item label="心跳间隔" prop="HeartbeatInterval">
            <el-input-number v-model="redis.HeartbeatInterval" :min="1" />
          </el-form-item>
          <el-form-item label="例外情况是否应包括可识别的详细信息" prop="IncludeDetailInExceptions">
            <el-switch v-model="redis.IncludeDetailInExceptions" />
          </el-form-item>
          <el-form-item label="异常是否应包括性能计数器详细信息" prop="IncludePerformanceCountersInExceptions">
            <el-switch v-model="redis.IncludePerformanceCountersInExceptions" />
          </el-form-item>
          <el-form-item label="要用于CLIENT SETINFO库名称调用Redis的库名称" prop="LibraryName">
            <el-input v-model="redis.LibraryName" />
          </el-form-item>
          <el-form-item label="用于在初级之间进行选择的平局决胜局" prop="TieBreaker">
            <el-input v-model="redis.TieBreaker" />
          </el-form-item>
          <el-form-item label="指示在连接之前是否应通过DNS解析终结点" prop="ResolveDns">
            <el-switch v-model="redis.ResolveDns" />
          </el-form-item>
          <el-form-item label="用户名" prop="UserName">
            <el-input v-model="redis.UserName" placeholder="用户名" maxlength="50" />
          </el-form-item>
          <el-form-item label="密码" prop="Pwd">
            <el-input v-model="memcached.Pwd" placeholder="密码" maxlength="50" />
          </el-form-item>
        </el-form>
      </el-tab-pane>
    </el-tabs>
  </el-card>
</template>

<script>
export default {
  components: {
  },
  props: {
    configValue: {
      type: String,
      default: null
    }
  },
  data() {
    const checkRedisIp = (rule, value, callback) => {
      if (this.formData.CacheType !== 1) {
        callback()
      } else if (this.redis.ServerIp.length === 0 && (this.redis.ConString == null || this.redis.ConString === '')) {
        callback(new Error('请输入Redis服务IP地址！'))
      } else {
        callback()
      }
    }
    const checkMemcachedIp = (rule, value, callback) => {
      if (this.formData.CacheType !== 0) {
        callback()
      } else if (this.memcached.ServerIp.length === 0) {
        callback(new Error('请输入Memcached服务IP地址！'))
      } else {
        callback()
      }
    }
    return {
      memcached: {
        ServerIp: []
      },
      redis: {
        ServerIp: []
      },
      redisRules: {
        ServerIp: [
          { validator: checkRedisIp, trigger: 'blur' }
        ]
      },
      memcachedRules: {
        ServerIp: [
          { validator: checkMemcachedIp, trigger: 'blur' }
        ]
      },
      activeName: 'memcached',
      formData: {}
    }
  },
  watch: {
    configValue: {
      handler(val) {
        this.reset()
      },
      immediate: true
    }
  },
  mounted() {
  },
  methods: {
    chioseCacheType() {
      if (this.formData.CacheType === 0) {
        this.activeName = 'memcached'
      } else if (this.formData.CacheType === 1) {
        this.activeName = 'redis'
      }
    },
    checkIp(item) {
      if (item.value == null || item.value === '') {
        item.isError = true
        item.error = 'Ip地址不能为空!'
      } else if (!RegExp('^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}([:]\d+){0,1}$').test(item.value)) {
        item.isError = true
        item.error = 'Ip地址格式错误!'
      } else {
        item.isError = false
      }
    },
    addIp() {
      this.memcached.ServerIp.push({
        value: null,
        isError: false,
        error: null
      })
    },
    removeIp(index) {
      this.memcached.ServerIp.splice(index, 1)
    },
    addRedisIp() {
      this.redis.ServerIp.push({
        value: null,
        isError: false,
        error: null
      })
    },
    removeRedisIp(index) {
      this.redis.ServerIp.splice(index, 1)
    },
    async getValue() {
      const rvalid = await this.$refs['redis'].validate()
      const mvalid = await this.$refs['memcached'].validate()
      if (mvalid && rvalid) {
        const res = {
          CacheType: this.formData.CacheType,
          Redis: {
            CommandMap: this.redis.CommandMap,
            ConString: this.redis.ConString,
            DefaultDatabase: this.redis.DefaultDatabase,
            AllowAdmin: this.redis.AllowAdmin,
            KeepAlive: this.redis.KeepAlive,
            ConnectRetry: this.redis.ConnectRetry,
            SyncTimeout: this.redis.SyncTimeout,
            AsyncTimeout: this.redis.AsyncTimeout,
            ConnectTimeout: this.redis.ConnectTimeout,
            ServerIp: this.redis.ServerIp.map(c => c.value),
            UserName: this.redis.UserName,
            Pwd: this.redis.Pwd,
            CheckCertificateRevocation: this.redis.CheckCertificateRevocation,
            ServiceName: this.redis.ServiceName,
            SetClientLibrary: this.redis.SetClientLibrary,
            ConfigCheckSeconds: this.redis.ConfigCheckSeconds,
            ConfigurationChannel: this.redis.ConfigurationChannel,
            BacklogPolicy: this.redis.BacklogPolicy,
            HeartbeatInterval: this.redis.HeartbeatInterval,
            IncludeDetailInExceptions: this.redis.IncludeDetailInExceptions,
            IncludePerformanceCountersInExceptions: this.redis.IncludePerformanceCountersInExceptions,
            LibraryName: this.redis.LibraryName,
            TieBreaker: this.redis.TieBreaker,
            ResolveDns: this.redis.ResolveDns
          },
          Memcached: {
            MinPoolSize: this.memcached.MinPoolSize,
            MaxPoolSize: this.memcached.MaxPoolSize,
            UserName: this.memcached.UserName,
            Pwd: this.memcached.Pwd,
            ConnectionTimeout: this.memcached.ConnectionTimeout,
            ServerIp: this.memcached.ServerIp.map(c => c.value)
          }
        }
        return res
      }
      return null
    },
    initConfig() {
      const res = JSON.parse(this.configValue)
      this.formData = {
        CacheType: res.CacheType
      }
      if (res.Redis != null) {
        const data = res.Redis
        if (data.ServerIp && data.ServerIp.length > 0) {
          data.ServerIp = data.ServerIp.map(c => {
            return {
              value: c,
              isError: false,
              error: null
            }
          })
        }
        this.redis = data
      } else {
        this.redis = {
          CommandMap: 1,
          ConString: null,
          DefaultDatabase: 0,
          AllowAdmin: true,
          KeepAlive: 60,
          ConnectRetry: 5,
          SyncTimeout: 5000,
          AsyncTimeout: 5000,
          ConnectTimeout: 5000,
          ServerIp: [],
          UserName: null,
          Pwd: null,
          CheckCertificateRevocation: false,
          ServiceName: null,
          SetClientLibrary: true,
          ConfigCheckSeconds: 60,
          ConfigurationChannel: null,
          BacklogPolicy: 0,
          HeartbeatInterval: 2,
          IncludeDetailInExceptions: true,
          IncludePerformanceCountersInExceptions: false,
          LibraryName: null,
          TieBreaker: '__Booksleeve_TieBreak',
          ResolveDns: false
        }
      }
      if (res.Memcached != null) {
        const data = res.Memcached
        if (data.ServerIp && data.ServerIp.length > 0) {
          data.ServerIp = data.ServerIp.map(c => {
            return {
              value: c,
              isError: false,
              error: null
            }
          })
        }
        this.memcached = data
      } else {
        this.memcached = {
          MinPoolSize: 2,
          MaxPoolSize: 100,
          UserName: null,
          Pwd: null,
          ConnectionTimeout: 3,
          ServerIp: []
        }
      }
    },
    reset() {
      if (this.configValue) {
        this.initConfig()
      } else {
        this.formData = {
          CacheType: 1
        }
        this.memcached = {
          MinPoolSize: 2,
          MaxPoolSize: 100,
          UserName: null,
          Pwd: null,
          ConnectionTimeout: 3,
          ServerIp: []
        }
        this.redis = {
          CommandMap: 1,
          ConString: null,
          DefaultDatabase: 0,
          AllowAdmin: true,
          KeepAlive: 60,
          ConnectRetry: 5,
          SyncTimeout: 5000,
          AsyncTimeout: 5000,
          ConnectTimeout: 5000,
          ServerIp: [],
          UserName: null,
          Pwd: null,
          CheckCertificateRevocation: false,
          ServiceName: null,
          SetClientLibrary: true,
          ConfigCheckSeconds: 60,
          ConfigurationChannel: null,
          BacklogPolicy: 0,
          HeartbeatInterval: 2,
          IncludeDetailInExceptions: true,
          IncludePerformanceCountersInExceptions: false,
          LibraryName: null,
          TieBreaker: '__Booksleeve_TieBreak',
          ResolveDns: false
        }
      }
    }
  }
}
</script>
